﻿using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;

namespace LogDemo
{
    [ProviderAlias("MyLogger")]
    public class MyLoggerProvider : ILoggerProvider
    {
        ConcurrentDictionary<string, ILogger> _loggerMap=new();
        Channel<MyLogInfo> channel = Channel.CreateUnbounded<MyLogInfo>();
        Task outputTask;
        CancellationTokenSource cancellationToken = new();


        public MyLoggerProvider()
        {
            this.cancellationToken = new CancellationTokenSource();
            outputTask=WriterLogger(cancellationToken.Token);
         }

        public ILogger CreateLogger(string categoryName)
        {
            var logger = _loggerMap.GetOrAdd(categoryName, name =>
                {
                    return new MyLogger(name, channel.Writer);
                });
            return logger;
        }

        public Task WriterLogger(CancellationToken stoppingToken)
        {
            var task = Task.Run(async () =>
             {
                 //while (stoppingToken.IsCancellationRequested == false)
                 //{
                 //    var logMsg = await channel.Reader.ReadAsync(stoppingToken);
                 //    if (logMsg != null)
                 //    {
                 //        Console.WriteLine(logMsg);
                 //    }
                 //}
                 await foreach(var logInfo in channel.Reader.ReadAllAsync(stoppingToken))
                 {
                     Console.ForegroundColor = ConsoleColor.Red;
                     Console.Write($"{logInfo.LogLevel}\t");
                     Console.ResetColor();
                     Console.WriteLine($"{logInfo.Date}\t {logInfo.Category}\t{logInfo.LogMessage}");
                     if (logInfo.Exception != null)
                     {
                         Console.WriteLine(logInfo.Exception.ToString());
                     }
                 }

             }, stoppingToken);
            return task;
        }

        public void Dispose()
        {
            cancellationToken?.Cancel();
            outputTask.Wait();
        }

    }
}
